package com.hsyg.netty;

import com.hsyg.netty.server.handler.ServerHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.HashMap;
import java.util.Map;


@Component
//实现ApplicationContextAware以获得ApplicationContext中的所有bean
public class NettyServer implements ApplicationContextAware {

  private static final Logger logger = LoggerFactory.getLogger(NettyServer.class);

  EventLoopGroup bossGroup;
  EventLoopGroup workGroup;


  private Map<String, Object> exportServiceMap = new HashMap<String, Object>();

  //@Value("${rpcServer.host:127.0.0.1}")
  String host = "127.0.0.1";

  //@Value("${rpcServer.ioThreadNum:5}")
  int ioThreadNum;

  //@Value("${rpcServer.backlog:1024}")
  int backlog;

  // @Value("${rpcServer.port:9090}")
  int port = 8888;

  /**
   * 启动
   *
   * @throws InterruptedException
   */
  @PostConstruct
  public void start() throws InterruptedException {
    bossGroup = new NioEventLoopGroup();
    workGroup = new NioEventLoopGroup();
    logger.debug("netty 启动");
    //服务端辅助启动类，用以降低服务端的开发复杂度
    ServerBootstrap bootstrap = new ServerBootstrap();
    bootstrap.group(bossGroup, workGroup)
      //实例化ServerSocketChannel
      .channel(NioServerSocketChannel.class)
      //设置ServerSocketChannel的TCP参数
      .option(ChannelOption.SO_BACKLOG, 1024)
      .childHandler(new ChildChannelHandler());

    // ChannelFuture：代表异步I/O的结果
    ChannelFuture future = bootstrap.bind(port).sync();
    future.channel().closeFuture().sync();
  }

  @PreDestroy
  public void stop() {
    logger.debug("netty 关闭");
  }

  /**
   * 利用此方法获取spring ioc接管的所有bean
   *
   * @param ctx
   * @throws BeansException
   */
  @Override
  public void setApplicationContext(ApplicationContext ctx) throws BeansException {

  }

  private class ChildChannelHandler extends ChannelInitializer<SocketChannel> {

    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
      //handler
      ch.pipeline().addLast(new ServerHandler());
    }

  }
}
